///
// * jdbm LICENSE v1.00
// *
// * Redistribution and use of this software and associated documentation
// * ("Software"), with or without modification, are permitted provided
// * that the following conditions are met:
// *
// * 1. Redistributions of source code must retain copyright
// *    statements and notices.  Redistributions must also contain a
// *    copy of this document.
// *
// * 2. Redistributions in binary form must reproduce the
// *    above copyright notice, this list of conditions and the
// *    following disclaimer in the documentation and/or other
// *    materials provided with the distribution.
// *
// * 3. The name "jdbm" must not be used to endorse or promote
// *    products derived from this Software without prior written
// *    permission of Cees de Groot.  For written permission,
// *    please contact cg@cdegroot.com.
// *
// * 4. Products derived from this Software may not be called "jdbm"
// *    nor may "jdbm" appear in their names without prior written
// *    permission of Cees de Groot.
// *
// * 5. Due credit should be given to the jdbm Project
// *    (http://jdbm.sourceforge.net/).
// *
// * THIS SOFTWARE IS PROVIDED BY THE ndbm PROJECT AND CONTRIBUTORS
// * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
// * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
// * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// * OF THE POSSIBILITY OF SUCH DAMAGE.
// *
// * Copyright 2000 (C) Cees de Groot. All Rights Reserved.
// * Contributions are Copyright (C) 2000 by their associated contributors.
// *
// * $Id: FreePhysicalRowIdPageManager.java,v 1.2 2001/11/17 16:14:25 boisvert Exp $
// 

//*************************************************************************
//**  Included in JDMB 1.0 port to SharpDBM;  11/2013 Cyrus Neah cneah@codingreal.com
//**  SharpDBM is an independent reimplementation of the JDBM 1.0 software library in C#  
//*************************************************************************

namespace SharpDBM.recman
{


///
// *  This class manages free physical rowid pages and provides methods
// *  to free and allocate physical rowids on a high level.
// 
	internal   class FreePhysicalRowIdPageManager
	{
	// our record file
		protected internal RecordFile _file;

	// our page manager
		protected internal PageManager _pageman;

//    *
//     *  Creates a new instance using the indicated record file and
//     *  page manager.
//     
 
//
		internal FreePhysicalRowIdPageManager(RecordFile file, PageManager pageman)
		{
			_file = file;
			_pageman = pageman;
		}


//    *
//     *  Returns a free physical rowid of the indicated size, or
//     *  null if nothing was found.
//     
 
//
		internal virtual Location @get(int size)
		{
		// Loop through the free physical rowid list until we find
		// a rowid that's large enough.
			Location retval = null;
			PageCursor curs = new PageCursor(_pageman, Magic.FREEPHYSIDS_PAGE);

			while (curs.next() != 0)
			{
				FreePhysicalRowIdPage fp = FreePhysicalRowIdPage.getFreePhysicalRowIdPageView(_file.get(curs.getCurrent()));
				int slot = fp.getFirstLargerThan(size);
				if (slot != -1)
				{
				// got one!
					retval = new Location(fp.get(slot));

					int slotsize = fp.get(slot).getSize();
					fp.free(slot);
					if (fp.getCount() == 0)
					{
					// page became empty - free it
						_file.release(curs.getCurrent(), false);
						_pageman.free(Magic.FREEPHYSIDS_PAGE, curs.getCurrent());
					}
					else
					{
						_file.release(curs.getCurrent(), true);
					}

					return retval;
					}
				else
				{
				// no luck, go to next page
					_file.release(curs.getCurrent(), false);
				}

			}
			return null;
		}

//    *
//     *  Puts the indicated rowid on the free list
//     
 
//
		internal virtual void put(Location rowid, int size)
		{

	  FreePhysicalRowId free = null;
	  PageCursor curs = new PageCursor(_pageman, Magic.FREEPHYSIDS_PAGE);
	  long freePage = 0;
	  while (curs.next() != 0)
	  {
		  freePage = curs.getCurrent();
		  BlockIo curBlock = _file.get(freePage);
		  FreePhysicalRowIdPage fp = FreePhysicalRowIdPage.getFreePhysicalRowIdPageView(curBlock);
		  int slot = fp.getFirstFree();
		  if (slot != -1)
		  {
		free = fp.alloc(slot);
		break;
		  }

		  _file.release(curBlock);
	  }
	  if (free == null)
	  {
	  // No more space on the free list, add a page.
		  freePage = _pageman.allocate(Magic.FREEPHYSIDS_PAGE);
		  BlockIo curBlock = _file.get(freePage);
		  FreePhysicalRowIdPage fp = FreePhysicalRowIdPage.getFreePhysicalRowIdPageView(curBlock);
		  free = fp.alloc(0);
	  }

	  free.setBlock(rowid.getBlock());
	  free.setOffset(rowid.getOffset());
	  free.setSize(size);
	  _file.release(freePage, true);
		}
	}

}